using System;
using System.Collections.Generic;
using Main.Details;
using Main.Event;
using Main.Save;
using UnityEngine;
using ZSW.Framework;

namespace Main.Inventory
{
    public class InventoryManager : ZSWF_Singleton<InventoryManager>, ISaveable
    {
        private ItemDataList_SO itemData;
        public InventoryBag_SO PlayerBag_Temp;
        private InventoryBag_SO PlayerBag_SO;
        private InventoryBag_SO currentBoxBag_SO;
        private BluePrintDataList_SO BluePrint_SO;
        [Header("交易")]
        public int playerMoney;

        public Dictionary<string, List<InventoryItem>> boxDataDic;

        public string GUID => GetComponent<DataGUID>().guid;

        public override void Init()
        {
            base.Init();
            GetData();
            boxDataDic = new Dictionary<string, List<InventoryItem>>();
            // MainEventSystem.InitFinish += () =>
            // {
            //     MainEventSystem.CallUpdateInventoryUI(InventoryLocation.Player, PlayerBag_SO.InventoryList);
            // };
            MainEventSystem.DropItemEvent += OnDropItem;
            MainEventSystem.HarvestAtPlayerPositionEvent += OnHarvestAtPlayerPosition;
            MainEventSystem.BuildFurnitureEvent += OnBuildFurnitureEvent;
            MainEventSystem.BaseBagOpenEvent += OnBaseBagOpen;
            MainEventSystem.StartNewGameEvent += OnStartNewGame;

            ISaveable saveable = this;
            saveable.RegisterSaveable();
        }

        private void OnStartNewGame(int obj)
        {
            PlayerBag_SO = Instantiate(PlayerBag_Temp);
            playerMoney = Settings.PlayerStartMoney;
            boxDataDic.Clear();

            MainEventSystem.CallUpdateInventoryUI(InventoryLocation.Player, PlayerBag_SO.InventoryList);
        }

        private void OnBaseBagOpen(SlotType type, InventoryBag_SO boxData)
        {
            if (type == SlotType.Box)
            {
                currentBoxBag_SO = boxData;
            }

        }

        private void OnBuildFurnitureEvent(Vector3 vector, int itemId)
        {
            RemoveItem(itemId, 1);

            if (BluePrint_SO.TryGetBluePrintDetails(itemId, out var bluePrintDetails))
            {
                foreach (var resource in bluePrintDetails.resourceItem)
                {
                    RemoveItem(resource.ItemID, resource.ItemAmount);
                }
            }
        }

        private void OnHarvestAtPlayerPosition(int id)
        {
            TryAddItemToBag(id);
        }

        private void OnDropItem(int itemId, Vector3 position, ItemType itemType)
        {
            RemoveItem(itemId, 1);
        }

        public bool TryGetItemDetails(int id, out ItemDetails itemDetails)
        {
            GetData();

            foreach (var item in itemData.ItemDetailsList)
            {
                if (item.ItemID == id)
                {
                    itemDetails = item;
                    return true;
                }
            }
            itemDetails = null;
            return false;
        }

        private void GetData()
        {
            if (itemData == null)
            {
                itemData = ZSWF_IOCContainer.Get<ItemDataList_SO>();
            }
            if (PlayerBag_SO == null)
            {
                PlayerBag_SO = ZSWF_IOCContainer.Get<InventoryBag_SO>();
            }
            if (BluePrint_SO == null)
            {
                BluePrint_SO = ZSWF_IOCContainer.Get<BluePrintDataList_SO>();
            }
        }

        /// <summary>
        /// 添加物品到Play的背包中
        /// </summary>
        /// <param name="itemID"></param>
        internal bool TryAddItemToBag(int itemID)
        {
            if (TryGetItemDetails(itemID, out var itemDetails))
            {
                if (TryAddItemToBag(itemID, 1))
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            else
            {
                Log($"物品列表找不到对应ID: {itemID} 的物品!");
                return false;
            }


        }

        /// <summary>
        /// 尝试获取背包中的相同物品的索引
        /// </summary>
        /// <param name="itemID"></param>
        /// <param name="ListIndex"></param>
        /// <returns></returns>
        private bool TryGetItemIndexInBag(int itemID, out int ListIndex)
        {
            ListIndex = -1;
            for (int i = 0; i < PlayerBag_SO.InventoryList.Count; i++)
            {
                int index = i;
                InventoryItem item = PlayerBag_SO.InventoryList[index];
                // 先查找是否有相同的物品
                if (item.ItemID == itemID)
                {
                    ListIndex = index;
                    return true;
                }
            }
            return false;
        }

        /// <summary>
        /// 尝试获取背包中的空位索引
        /// </summary>
        /// <param name="ListIndex"></param>
        /// <returns></returns>
        private bool TryGetEmptySlotInBag(out int ListIndex)
        {
            ListIndex = -1;
            for (int i = 0; i < PlayerBag_SO.InventoryList.Count; i++)
            {
                int index = i;
                InventoryItem item = PlayerBag_SO.InventoryList[index];
                // 先查找是否有相同的物品
                if (item.ItemAmount == 0)
                {
                    ListIndex = index;
                    return true;
                }
            }
            return false;
        }

        /// <summary>
        /// 尝试添加物品到背包中
        /// </summary>
        /// <param name="itemID"></param>
        /// <param name="ItemAmount"></param>
        /// <param name="index"></param>
        public bool TryAddItemToBag(int itemID, int ItemAmount, int index = -1)
        {
            if (index < 0 || index >= PlayerBag_SO.InventoryList.Count)
            {
                //尝试获取相同物体索引
                if (TryGetItemIndexInBag(itemID, out int ListIndex))
                {
                    index = ListIndex;
                }
                // 尝试获取空位索引
                else if (TryGetEmptySlotInBag(out int emptyIndex))
                {
                    index = emptyIndex;
                }
                // 背包已满
                else
                {
                    Log($"无法添加物品{itemID} 到背包中. 原因: 背包已满");
                    return false;
                }
            }

            Log($"当前索引:{index}");

            var InventoryItem = PlayerBag_SO.InventoryList[index];

            //  空位情况下,设置ID
            if (InventoryItem.ItemID == 0)
            {
                InventoryItem.SetItemID(itemID);
            }

            // ID不匹配
            if (InventoryItem.ItemID != itemID)
            {
                Log($"无法添加物品{itemID} 到背包中. 原因: ID不匹配 物品ID{itemID} 背包物品ID{InventoryItem.ItemID}");
                return false;
            }

            // 更新数据
            InventoryItem.AddItem(ItemAmount);

            PlayerBag_SO.InventoryList[index] = InventoryItem;

            MainEventSystem.CallUpdateInventoryUI(InventoryLocation.Player, PlayerBag_SO.InventoryList);

            return true;
        }

        public void SwapItem(SlotType slotType, int slotIndex1, int slotIndex2)
        {
            if (slotType == SlotType.Bag)
            {
                var item1 = PlayerBag_SO.InventoryList[slotIndex1];
                var item2 = PlayerBag_SO.InventoryList[slotIndex2];
                PlayerBag_SO.InventoryList[slotIndex1] = item2;
                PlayerBag_SO.InventoryList[slotIndex2] = item1;

                MainEventSystem.CallUpdateInventoryUI(InventoryLocation.Player, PlayerBag_SO.InventoryList);
            }
        }

        /// <summary>
        /// 交换背包和箱子中的物品数据
        /// </summary>
        /// <param name="fromLocation"></param>
        /// <param name="targetLocation"></param>
        /// <param name="fromIndex"></param>
        /// <param name="targetIndex"></param>
        public void SwapItem(InventoryLocation fromLocation, InventoryLocation targetLocation, int fromIndex, int targetIndex)
        {
            var fromList = GetItemList(fromLocation);
            var targetList = GetItemList(targetLocation);

            InventoryItem fromItem = fromList[fromIndex];

            if (targetIndex < targetList.Count)
            {
                InventoryItem targetItem = targetList[targetIndex];

                if (targetItem.ItemID != 0 && fromItem.ItemID != targetItem.ItemID)
                {
                    fromList[fromIndex] = targetItem;
                    targetList[targetIndex] = fromItem;
                }
                else if (targetItem.ItemID != 0 && fromItem.ItemID == targetItem.ItemID)
                {
                    targetItem.ItemAmount += fromItem.ItemAmount;
                    targetList[targetIndex] = targetItem;
                    fromList[fromIndex] = new InventoryItem();
                }
                else if (targetItem.ItemID == 0)
                {
                    targetList[targetIndex] = fromItem;
                    fromList[fromIndex] = new InventoryItem();
                }
            }

            MainEventSystem.CallUpdateInventoryUI(fromLocation, fromList);
            MainEventSystem.CallUpdateInventoryUI(targetLocation, targetList);
        }


        private List<InventoryItem> GetItemList(InventoryLocation location)
        {
            switch (location)
            {
                case InventoryLocation.Player:
                    return PlayerBag_SO.InventoryList;
                case InventoryLocation.Box:
                    return currentBoxBag_SO.InventoryList;
                default:
                    return null;
            }
        }

        /// <summary>
        /// 移除指定数量的背包物品
        /// </summary>
        /// <param name="itemID"></param>
        /// <param name="removeAmount"></param>
        private void RemoveItem(int itemID, int removeAmount)
        {
            if (TryGetItemIndexInBag(itemID, out int ListIndex))
            {
                Log($"移除物品 {itemID}当前数量{PlayerBag_SO.InventoryList[ListIndex].ItemAmount} 移除数量{removeAmount}");
                if (PlayerBag_SO.InventoryList[ListIndex].ItemAmount > removeAmount)
                {
                    PlayerBag_SO.InventoryList[ListIndex] = new InventoryItem() { ItemID = itemID, ItemAmount = PlayerBag_SO.InventoryList[ListIndex].ItemAmount - removeAmount };
                    Log($"刷新物品数量 当前:{PlayerBag_SO.InventoryList[ListIndex].ItemAmount}");
                }
                else if (PlayerBag_SO.InventoryList[ListIndex].ItemAmount == removeAmount)
                {
                    Log("物品数量为0,清空物品");
                    PlayerBag_SO.InventoryList[ListIndex] = new InventoryItem();
                }

                Log($"物品当前数量 :{PlayerBag_SO.InventoryList[ListIndex].ItemAmount}");

                MainEventSystem.CallUpdateInventoryUI(InventoryLocation.Player, PlayerBag_SO.InventoryList);
            }
        }

        public void TradeMoney(ItemDetails itemDetails, int amount, bool isSell)
        {
            int cost = itemDetails.ItemPrice * amount;
            TryGetItemIndexInBag(itemDetails.ItemID, out int index);

            if (isSell)
            {
                if (PlayerBag_SO.InventoryList[index].ItemAmount >= amount)
                {
                    RemoveItem(itemDetails.ItemID, amount);

                    cost = (int)(cost * itemDetails.SellPercentage);

                    playerMoney += cost;
                }
            }
            else if (playerMoney - cost >= 0)
            {
                // 背包中存在相同物品时
                if (TryAddItemToBag(itemDetails.ItemID, amount))
                {
                    playerMoney -= cost;
                }
            }

            // 刷新UI
            MainEventSystem.CallUpdateInventoryUI(InventoryLocation.Player, PlayerBag_SO.InventoryList);

        }

        /// <summary>
        /// 检测背包中的资源是否满足蓝图需求
        /// </summary>
        /// <param name="itemID"></param>
        /// <returns></returns>
        public bool CheckBluePrintStock(int itemID)
        {
            if (BluePrint_SO.TryGetBluePrintDetails(itemID, out BluePrintDetails bluePrintDetails))
            {
                foreach (var resource in bluePrintDetails.resourceItem)
                {
                    // 检测背包中是否存在指定物体并且满足数量要求
                    if (PlayerBag_SO.TryGetInventoryItem(resource.ItemID, out var item) && item.ItemAmount >= resource.ItemAmount)
                    {
                        continue;
                    }
                    else
                    {
                        return false;
                    }
                }
            }
            return true;
        }

        public bool TryGetBoxDataList(string key, out List<InventoryItem> list)
        {
            if (boxDataDic.TryGetValue(key, out list))
            {
                return true;
            }
            return false;
        }

        public void AddBoxData(Box box)
        {
            var key = box.name + box.index;
            boxDataDic.TryAdd(key, box.boxBag.InventoryList);
        }

        public GameSaveData GenerateSaveData()
        {
            var data = new GameSaveData();
            data.playerMoney = playerMoney;

            data.inventoryDict = new Dictionary<string, List<InventoryItem>>();
            data.inventoryDict.Add(PlayerBag_SO.name, PlayerBag_SO.InventoryList);

            foreach (var box in boxDataDic)
            {
                data.inventoryDict.Add(box.Key, box.Value);
            }
            return data;
        }

        public void RestoreData(GameSaveData data)
        {
            this.playerMoney = data.playerMoney;

            this.PlayerBag_SO.InventoryList = data.inventoryDict[PlayerBag_SO.name];

            foreach (var box in data.inventoryDict)
            {
                if (box.Key != PlayerBag_SO.name)
                {
                    boxDataDic.TryAdd(box.Key, box.Value);
                }
            }

            MainEventSystem.CallUpdateInventoryUI(InventoryLocation.Player, PlayerBag_SO.InventoryList);
        }
    }
}